"""
@Type doc
@Author xjp
@CreateDate 2025-01-17_16:02:22
@Description 匹配日志数据
@Version v1.0 
@Copyright Copyright (c) 2025 by xiaoxiang ,ALL Rights Reserved
"""

import regex as re

"""
@Type class
@Author xjp
@CreateDate 2025-01-17_16:14:36
@Description 匹配日志数据类
"""
class MatchData:
    def __init__(self):
        # 初始化正则表达式对象
        # 匹配实体
        #self.patternEntity = re.compile(r'<(\w+)>(.*?)</\1>')
        self.patternEntity = re.compile(r'<(\w+-\d+)>([^\s]*)</\1>')
        # 匹配非实体
        self.patternNormal = re.compile(r'(^<\w+>.)|(.</\w+>$)')
        # 基准结果 TP,TN,FP,FN
        self.TP = 0
        self.TN = 0
        self.FP = 0
        self.FN = 0
    """
    @Type function
    @Author xjp
    @CreateDate 2025-01-17_16:15:53
    @Description 匹配两条标记的日志数据 
    @Param oldData:原始数据,即标注的数据;newData:计算得到的结果数据;
    @Return (TP,TN,FP,FN):(是实体且被识别出来,非实体但被识别出来,非实体也未被识别出来,是实体但未被识别出来)
    """
    def matchTwoMarkedLog(self, oldData:str, newData:str):
        TP = 0
        TN = 0
        FP = 0
        FN = 0
        if oldData == newData:
            # 获取实体数量
            entities = self.patternEntity.findall(oldData)
            # 获取全部token数量
            lenTokens = len(oldData.split(" "))
            TP = len(set([e[0] for e in entities]))
            TN = 0
            FP = lenTokens - len(entities)
            FN = 0
            return (TP,TN,FP,FN)


        # 分割token
        tokensOld = oldData.split(" ")
        tokensNew = newData.split(" ")

        TP,TN,FP,FN = self.__calcBase(tokensOld, tokensNew)
        self.TP += TP
        self.TN += TN
        self.FP += FP
        self.FN += FN

        # 
        #for t in tokensOld:
            #normal = self.patternNormal.search(t)
            #if normal == None:
                #print(t)
        #normal = self.patternNormal.findall(" " + oldData+ " ")

        #print(normal)
    



    """
    @Type function
    @Author xjp
    @CreateDate 2025-01-20_09:16:21
    @Description 计算基本指标             
    @Param 
    @Return 
    """
    def __calcBase(self,tokensOld, tokensNew):
        index = 0
        # 存放标注的token中的token的组合
        tempOld = []
        # 划分旧的标注数据中的队列
        while index < len(tokensOld):
            # 开始判断
            tempRes = self.patternEntity(tokensOld[index])
            temp = [0,0,""]
            # 判断是否是实体
            if len(tempRes)!=0:
                # 如果是实体
                # 先获取实体类型
                entType = tempRes[0][0]
                # 加入到临时结果中
                temp[0] = 1
                temp[1] += 1
                temp[2] = tokensOld[index] + " "
                index +=1
                while index < len(tokensOld):
                    tempRes = self.patternEntity(tokensOld[index])
                    # 判断是否是实体
                    if len(tempRes)!=0:
                        #确认为实体 
                        # 判断实体类型是否相同
                        if tempRes[0][0] == entType:
                            # 为同一类型实体
                            temp[1] += 1
                            temp[2] += tokensOld[index] + " "
                            index += 1
                        else:
                            index -=1
                            break
                    else:
                        # 不是实体
                        index -=1
                        break
            else:
                temp[0] = 0
                temp[1] = 1
                temp[2] = tokensOld[index]
            tempOld.append(temp)
        # 初始化计算基准
        TP,TN,FP,FN = 0,0,0,0
        # 开始计算
        index = 0
        # 遍历每一个组合
        for tokens in tempOld:
            # 对应位置不是实体
            if tokens[0] == 0:
                # 都不是实体的情况
                if tokens[2] == tokensNew[index]:
                    # 原数据不是实体,测试数据也不是实体
                    FP +=1
                else:
                    # 原数据不是实体,测试数据给标注为实体
                    FN += 1
                index +=1
            else:# 原数据为实体的情况
                end = tokens[1]
                temp = ""
                # 拼接测试数据中识别的数据
                for i in range(end):
                    temp += tokensNew[index+i] + " "
                # 如果完全相同
                if temp == tokens[2]:
                    # 判断测试数据中前后的实体类型是否和判断的实体类型相同
                    entType = self.patternEntity(tokensNew[index])[0][0]
                    flag = False
                    # 之前的实体类型
                    if index-1>=0:
                        entBefore = self.patternEntity(tokensNew[index-1])
                        if len(entBefore)!=0:
                            if entBefore[0][0] == entType:
                               # 此时判断范围之前的实体类型和范围内的实体类型相同,为错误的情况
                               flag = True
                    # 如果之前的是正确的则判断是否的token
                    if flag != True:
                        if index + end < len(tokensNew):
                            entAfter = self.patternEntity(tokensNew[index+end])
                            if len(entAfter)!=0:
                                if entAfter[0][0] == entType:
                                    # 此时判断范围之前的实体类型和范围内的实体类型相同,为错误的情况
                                    flag = True
                    if flag == True:
                        TN +=1
                    else:
                        TP +=1
                else:
                    TN +=1
        return TP,TN,FP,FN
                        

                        





    """
    @Type function
    @Author xjp
    @CreateDate 2025-01-20_09:15:48
    @Description 计算评估标准 
    @Param 
    @Return 
    """
    def __calcEvaluation(self):
        
        self.FNR = (self.FN)/(self.)


    """
    @Type function
    @Author xjp
    @CreateDate 2025-01-17_17:28:55
    @Description 判断一个token是否是实体 
    @Param 
    @Return 
    """
    def __isEntity(self, token:str):
        res = self.patternNormal(token)
        print(res)



if __name__ == "__main__":
    obj = MatchData()
    text1 = "sadw dwqsd fsda <TIME-1>sadaf3w</TIME-1> !! fdijofo <TIME-2> sdwad <PP-1>feq</PP-1> <PP-1>dwqe</PP-1> <TIME-2></AA></TIME-2>"
    text2 = "sasdw dwqsd fsda <TIME>sadaf3w</TIME> !! fdijofo <TIME> sdwad <PP>feq dwqe</PP> </AA>"
    obj.matchTwoMarkedLog(text1, text2)


